// +----------------------------------------------------------------------
// | ILDP-three-dimensional系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.lyltop.top All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 彦麟工作室 <yanlinstudio@126.com>
// +----------------------------------------------------------------------
// | Name: 刘彦麟
// +----------------------------------------------------------------------
// | FILE_NAME: geometry.ts
// +----------------------------------------------------------------------
// | Date: 2022/6/15 10:06
// +----------------------------------------------------------------------
import * as THREE from "three";
import {Camera, Scene, WebGLRenderer} from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {TransformControls} from "three/examples/jsm/controls/TransformControls";
import {Object3D} from "three/src/Three";
import {useThreeDimensional} from "../../../storage/models/threeDimensional";

// import IndexedDB from "./indexedDB";


class Geometry {
    get object3DList(): Object3D[] {
        return this._object3DList;
    }

    private control: TransformControls | null = null;
    private object3D: any;
    private renderer: WebGLRenderer;
    private scene: Scene;
    private camera: Camera;
    private controls: OrbitControls;
    private index = 0;
    private _object3DList: Object3D[] = [];
    private threeDStore: any;

    // private db:IndexedDB;

    constructor(renderer: WebGLRenderer, scene: Scene, camera: Camera, controls: OrbitControls) {
        this.renderer = renderer;
        this.scene = scene;
        this.camera = camera;
        this.controls = controls;
        // this.db = new IndexedDB();
        this.threeDStore = useThreeDimensional();
    }

    public AddBoxGeometry() {
        const geometry = new THREE.BoxGeometry(10, 10, 10)
        const material = new THREE.MeshBasicMaterial({color: 0xffff00});
        const box = new THREE.Mesh(geometry, material);
        box.name = `box_${this.index}`;
        this.scene.add(box)
        this.AddGeometry();
    }

    public AddCircleGeometry() {
        const geometry = new THREE.CircleGeometry(5, 32);
        const material = new THREE.MeshBasicMaterial({color: 0xffff00})
        const circle = new THREE.Mesh(geometry, material);
        circle.name = `circle_${this.index}`;
        this.scene.add(circle)
        this.AddGeometry();
    }

    public AddConeGeometry() {
        const geometry = new THREE.ConeGeometry(5, 20, 32);
        const material = new THREE.MeshBasicMaterial({color: 0xffff00});
        const cone = new THREE.Mesh(geometry, material);
        cone.name = `cone_${this.index}`;
        this.scene.add(cone);
        this.AddGeometry();
    }

    public AddCylinderGeometry() {
        const geometry = new THREE.CylinderGeometry(5, 5, 20, 32);
        const material = new THREE.MeshBasicMaterial({color: 0xffff00});
        const cylinder = new THREE.Mesh(geometry, material);
        cylinder.name = `cylinder_${this.index}`;
        this.scene.add(cylinder);
        this.AddGeometry();
    }

    public AddSphereGeometry(){
        const geometry = new THREE.SphereGeometry( 15, 32, 16 );
        const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
        const sphere = new THREE.Mesh( geometry, material );
        sphere.name = `sphere_${this.index}`;
        this.scene.add(sphere);
        this.AddGeometry();
    }

    public AddTorusGeometry(){
        const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 );
        const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
        const torus = new THREE.Mesh( geometry, material );
        torus.name = `torus_${this.index}`;
        this.scene.add(torus);
        this.AddGeometry();
    }

    public AddTorusKnotGeometry(){
        const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 );
        const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
        const torusKnot = new THREE.Mesh( geometry, material );
        torusKnot.name = `torusKnot_${this.index}`;
        this.scene.add(torusKnot);
        this.AddGeometry();
    }

    public AddPlaneGeometry(){
        const geometry = new THREE.PlaneGeometry( 10, 10 );
        const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
        const plane = new THREE.Mesh( geometry, material );
        plane.name = `plane_${this.index}`;
        this.scene.add(plane);
        this.AddGeometry();
    }


    public GetObject3D(object3D: Object3D | null) {
        if (object3D) {
            this.object3D = object3D;
            this.Transform();
        }

    }

    private async AddGeometry() {
        const length = this.scene.children.length;
        let scene = {...this.scene};
        scene.children = []
        this.scene.children.forEach((item, i) => {
            if (item.name !== 'transformControl' && item.name !== 'axesHelper' && item.name !== 'gridHelperSc') {
                scene.children.push(item);
                if(i === length - 1){
                    this.object3D = item;
                }
            }
        })
        this.index += 1;
        this._object3DList.push(this.object3D);
        await this.Transform();
        this.threeDStore.setLayerList([this.camera, scene]);
    }

    private Transform() {
        this.threeDStore.setElement(this.object3D);
        if (this.control === null) {
            this.control = new TransformControls(this.camera, this.renderer.domElement);
            this.control.name = "transformControl";
        }
        if (this.control) {
            this.control.addEventListener('dragging-changed', (event) => {
                if (this.controls) {
                    this.controls.enabled = !event.value;
                }
            });
            this.control.attach(this.object3D);
            this.scene.add(this.control);
        }
    }
}

export default Geometry
